const fs = require("fs");
const { Command } = require("commander");
const archiver = require("archiver");
const { NodeSSH } = require("node-ssh");

// "archiver": "^6.0.1",
// "commander": "^11.1.0",
// "node-ssh": "^13.1.0",

const program = new Command();
program
  .version("1.0.0")
  .option("--zip_dir [value]", "subproject dir")
  .option("--zip", "need zip")
  .option("--dist [value]", "upload file name , contain surfix")
  .option(
    "--service [value]",
    "service's working dir name, folder in nginx's work dir."
  )
  .option("--env_mode [value]", "env mode")
  .parse(process.argv);

const options = program.opts();

let remote_host = "";
let remote_user = "";
let remote_pwd = "";

const cwd = process.cwd();
const dist_zip = `${options.dist || ""}`;
const local_zip = `${cwd}/${dist_zip}`;
let service_root = "/usr/share/nginx/html/app1";
const service_dir = `${options.service || ""}`;

if (!process.argv.slice(2).length) {
  program.outputHelp();
} else if (!options.zip_dir || !options.dist || !options.service) {
  program.outputHelp();
} else {
  console.log(options);
  if (!options.env_mode || options.env_mode === "dev") {
    remote_host = "172.22.3.106";
    remote_user = "root";
    remote_pwd = "ficlIqgq9h4lIVZy";
    service_root = "/usr/share/nginx/html/vite-ts";
  } else if (options.env_mode === "prod") {
    remote_host = "";
    remote_user = "";
    remote_pwd = "";
    service_root = "";
  }

  if (fs.existsSync(local_zip)) {
    fs.unlinkSync(local_zip);
  }

  let output;
  let archive;
  // create a file to stream archive data to.
  if (options.zip) {
    output = fs.createWriteStream(local_zip);
    archive = archiver("zip", {
      // Sets the compression level.
      zlib: {
        level: 5,
      },
    });

    // listen for all archive data to be written
    // 'close' event is fired only when a file descriptor is involved
    output.on("close", function () {
      console.log(archive.pointer() + " total bytes");
      console.log(
        "archiver has been finalized and the output file descriptor has closed."
      );

      upload();

      // new Promise((resolve) => {
      //   setTimeout(() => resolve(), 2000)
      // }).then(() => upload())
    });

    // This event is fired when the data source is drained no matter what was the data source.
    // It is not part of this library but rather from the NodeJS Stream API.
    // @see: https://nodejs.org/api/stream.html#stream_event_end
    output.on("end", function () {
      console.log("Data has been drained");
    });

    // good practice to catch warnings (ie stat failures and other non-blocking errors)
    archive.on("warning", function (err) {
      if (err.code === "ENOENT") {
        // log warning
        console.log(`${JSON.stringify(err)}`);
      } else {
        // throw error
        throw err;
      }
    });

    // good practice to catch this error explicitly
    archive.on("error", function (err) {
      throw err;
    });

    // pipe archive data to the file
    archive.pipe(output);

    // 添加src目录，第二个参数表示在压缩文件中不建立文件夹，散落在root目录
    archive.directory(`${cwd}/${options.zip_dir}`, false);

    // 添加src目录，第二个参数表示在压缩文件中建立文件夹的名字
    // archive.directory(`${cwd}/${options.zip_dir}`, `${service_dir}`);

    archive.finalize();
  } else {
    // 不用压缩文件，就上传指定文件
    upload();
  }
}

function upload() {
  const ssh = new NodeSSH();

  ssh
    .connect({
      host: remote_host,
      username: remote_user,
      password: remote_pwd,
    })
    .then(
      () => {
        return ssh
          .exec(`rm -rf ${service_root}/${service_dir}/*`, [], {
            cwd: "",
            onStdout(chunk) {
              console.log("stdoutChunk", chunk.toString("utf8"));
            },
            onStderr(chunk) {
              console.log("stderrChunk", chunk.toString("utf8"));
            },
          })
          .then(() => {
            console.log("uploading");
            return ssh.putFile(local_zip, `${dist_zip}`);
          })
          .then(() => {
            console.log("uploaded file, unzipping file");
            return ssh.exec(
              `unzip -d ${service_root}/${service_dir} ${dist_zip}`,
              [],
              {
                cwd: "",
                onStdout(chunk) {
                  console.log("stdoutChunk", chunk.toString("utf8"));
                },
                onStderr(chunk) {
                  console.log("stderrChunk", chunk.toString("utf8"));
                },
              }
            );
          })
          .then(() => {
            console.log("unzipped file, delete uploaded file");
            return ssh.exec(`rm -f ${dist_zip}`, [], {
              cwd: "",
              onStdout(chunk) {
                console.log("stdoutChunk", chunk.toString("utf8"));
              },
              onStderr(chunk) {
                console.log("stderrChunk", chunk.toString("utf8"));
              },
            });
          })
          .then(() => {
            console.log("All done!");
            return ssh.dispose();
          });
      },
      (error) => {
        console.log("Something's wrong:");
        console.log(error);
      }
    );
}
